package model;
import java.awt.Color;
import java.util.ArrayList;
import javax.swing.JColorChooser;
import view.Canvas;
import view.Designer;
import model.PrescriptionBox;
import model.PrescriptionObject;
/**
 * A class to model a singular prescription
 * @author Mohammad Abdullah, Daniel Bond
 * @version 1.0
 */
public class Prescription {
	private ArrayList<PrescriptionObject> objects;
	private static Prescription instance;
	private Color bgColour;
	private String name;
	private int width;
	private int height;
	private String serialNo;
	private boolean hasChanged;
	private String filename;
	/**
	 * Constructor creates an empty Prescription with a name,
	 * serial number, and type.
	 */
	private Prescription(){
		objects = new ArrayList<PrescriptionObject>();
		bgColour = Constants.DEFAULT_FILL_COLOUR;
		width = Constants.DEFAULT_PRES_WIDTH;
		height = Constants.DEFAULT_PRES_HEIGHT;
		name = Constants.DEFAULT_PRES_NAME;
		serialNo = Constants.DEFAULT_SERIAL_NO;
		filename = Constants.DEFAULT_FILENAME;
		hasChanged = false;
	}	/**	 * Checks if an instance of the prescription is already created. if so, it returns that instance	 * if not, then it creates a new instance and returns that.	 * @return the prescription object	 */
	public static Prescription getInstance()
	{
		if (instance == null)
		{
			instance = new Prescription();
		}
		return instance;
	}	/**	 * Sets the state of the prescription to "changed"	 */
	public void setChanged(){
		hasChanged = true;
	}	/**	 * Sets the state of the prescription to "unchanged"	 */
	public void setUnchanged(){
		hasChanged = false;
	}	/**	 * Checks the state of the prescription	 * @return returns the current state of the prescription	 */
	public boolean hasChanged(){
		return hasChanged;
	}
	/**	 * Sends the current object selected to the back of the canvas	 * @param index the object index to send to the back of the canvas	 */
	public void sendToBack(int index){
		ArrayList<PrescriptionObject> temp = new ArrayList<PrescriptionObject>();
		temp.add(objects.get(index));
		for(int i = 0; i < objects.size(); i++){
			if(i != index){
				temp.add(objects.get(i));
			}
		}
		objects.clear();
		objects.addAll(temp);
	}
	/**	 * Sends the current object selected to the front of the canvas	 * @param index the object index to send to the front of the canvas	 */
	public void bringToFront(int index){
		ArrayList<PrescriptionObject> temp = new ArrayList<PrescriptionObject>();
		for(int i = 0; i < objects.size(); i++){
			if(i != index){
				temp.add(objects.get(i));
			}
		}
		temp.add(objects.get(index));
		objects.clear();
		objects.addAll(temp);
	}	/**	 * sets the name of the prescription.	 * @param newName the new name to set for the prescription	 */
	public void setName(String newName){
		this.name = newName;
		setChanged();
		Canvas.getInstance().repaint();
	}	/**	 * Gets the name of the prescription	 * @return the name of the prescription	 */
	public String getName(){
		return this.name;
	}	/**	 * Sets the serial number of the prescription	 * @param newSerialNo the new serial number of the prescription	 */
	public void setSerialNumber(String newSerialNo){
		this.serialNo = newSerialNo;
		setChanged();
	}
	/**	 * Gets the serial number of the prescription	 * @return the serial number of the prescription	 */
	public String getSerialNo(){
		return this.serialNo;
	}
	/**	 * Sets the height of the prescription	 * @param newHeight the new height of the prescription	 */
	public void setHeight(int newHeight){
		this.height = newHeight;
		setChanged();
	}
	/**	 * Gets the height of the prescription	 * @return the height of the prescription	 */
	public int getHeight(){
		return height;
	}	/**	 * Sets the width of the prescription	 * @param newWidth the new width of the prescription	 */
	public void setWidth(int newWidth){
		this.width = newWidth;
		setChanged();
	}	/**	 * Gets the width of the prescription	 * @return the current width of the prescription	 */
	public int getWidth(){
		return width;
	}	/**	 * Sets the background colour of the prescription by merging RGB values	 * @param red the red component of the RGB combination	 * @param green the green component of the RGB combination	 * @param blue the blue component of the RGB combination	 */
	public void setBGColour(int red, int green, int blue){
		bgColour = new Color(red, green, blue);
		setChanged();
	}	/**	 * Sets the background colour of the prescription by utilising a Java.awt.color object	 * @param newColour the colour to set the prescription background to	 */
	public void setBGColour(Color newColour){
		bgColour = newColour;
		setChanged();
	}
	/**	 * Gets the background colour of the prescription	 * @return the colour of the background on the prescription	 */
	public Color getBGColour(){
		return bgColour;
	}
	/**	 * Gets the list of objects currently on the prescription	 * @return the ArrayList of objects on the prescription	 */
	public ArrayList<PrescriptionObject> objects(){
		return objects;
	}	/**	 * Adds an object to the prescription	 * @param object the object to add to the prescription	 */
	public void addObject(PrescriptionObject object){
		objects.add(object);
		setChanged();
	}	/**	 * Adds an object to the prescription	 * @param object the object to add to the prescription	 * @param x the x coordinate of the object	 * @param y the y coordinate of the object	 */
	public void addObject(PrescriptionObject object, int x, int y){
		object.setX(x);
		object.setY(y);
		objects.add(object);
		setChanged();
	}
	/**	 * Removes an object from the prescription 	 * @param index the index of the object to be removed.	 */
	public void removeObject(int index){
		if (!(objects.size() == 0)){			try{				objects.remove(index);			}catch(IndexOutOfBoundsException e){				Designer.getInstance().showMessageDialog("You have not selected an item to delete");			}
		}
	}
	/**
	 * Changes the background colour of the prescription
	 */
	public void changeBGColour(){
		Color newBGColour = JColorChooser.showDialog(Designer.getInstance(),"Background Colour Choose", bgColour);
		if(newBGColour != null){
			this.setBGColour(newBGColour);
		}
	}	/**	 * Changes the height of the prescription	 * @param height the new height of the prescription	 */
	public void changePrescriptionHeight(String height){		try{			int newHeight = Integer.parseInt(height);			setHeight(newHeight);		}catch(NumberFormatException e){			System.out.println("Failed to parse in method: changePrescriptionHeight()");			e.printStackTrace();		}
	}	/**	 * Changes the width of the prescription	 * @param width the new width of the prescription	 */
	public void changePrescriptionWidth(String width){		try{			int newWidth = Integer.parseInt(width);			setWidth(newWidth);		}catch(NumberFormatException e){			System.out.println("Failed to parse in method: changePrescriptionWidth");			e.printStackTrace();		}
	}
	/**
	 * Changes line colour of selected object
	 */
	public Color changeLineColour(){
		Color newLineColour = JColorChooser.showDialog(Designer.getInstance(), "Line Colour Choose", Color.black);
		if(newLineColour != null){
			if(objects.get(getSelectedIndex()) != null){
				if((objects.get(getSelectedIndex()).isSelected()) && (objects.get(getSelectedIndex()) instanceof PrescriptionBox)){
					((PrescriptionBox) objects.get(getSelectedIndex())).setLineColour(newLineColour);
					((PrescriptionBox) objects.get(getSelectedIndex())).setTransparent(false);
				}else if((objects.get(getSelectedIndex()).isSelected()) && (objects.get(getSelectedIndex()) instanceof PrescriptionLabel)){					((PrescriptionLabel) objects.get(getSelectedIndex())).setLineColour(newLineColour);					((PrescriptionLabel) objects.get(getSelectedIndex())).setTransparent(false);				}
				objects.get(getSelectedIndex()).setLineColour(newLineColour);
				setChanged();
			}
		}
		return newLineColour;
	}	/**	 * Changes the line width of an object on the prescription	 * @param width the new line width of the object	 */
	public void changeLineWidth(float width){
		if (objects.size() != 0){
			if(objects.get(getSelectedIndex()) != null){
				if(objects.get(getSelectedIndex()).isSelected()){
					objects.get(getSelectedIndex()).setLineWidth(width);
				}
				setChanged();
			}
		}
	}	/**	 * Changes the name of the object	 * @param name the new name of the object	 */
	public void changeName(String name){		
		objects.get(getSelectedIndex()).setName(name);
		setChanged();	
	}	/**	 * Gets the currently selected object's index.	 * @return the index of the currently selected object	 */
	public int getSelectedIndex(){
		return Designer.getInstance().getObjectIndex();
	}
	/**
	 * Change the fill colour of all the objects on the prescription
	 */
	public void changeFillColourAll(){
		Color newFillColour = JColorChooser.showDialog(Designer.getInstance(), "Fill Colour Choose", Color.WHITE);
		if(newFillColour != null){			if(objects.get(getSelectedIndex()) instanceof PrescriptionBox){				for(PrescriptionObject obj : objects){					if(obj instanceof PrescriptionBox){						obj.setFillColour(newFillColour);						obj.setTransparent(false);					}				}			}else if(objects.get(getSelectedIndex()) instanceof PrescriptionLabel){				for(PrescriptionObject obj : objects){					if(obj instanceof PrescriptionLabel){						obj.setFillColour(newFillColour);						obj.setTransparent(false);					}				}			}
			setChanged();
		}
	}	/**	 * Changes the file colour of one selected object	 * @param index the index of the object to change the fill colour of	 */	public void changeFillColour(int index){		Color newFillColour = JColorChooser.showDialog(Designer.getInstance(), "Fill Colour Choose", Color.WHITE);		if(newFillColour != null){			if(objects.get(index) instanceof PrescriptionBox){				((PrescriptionBox) objects.get(index)).setFillColour(newFillColour);				((PrescriptionBox) objects.get(index)).setTransparent(false);			}else if(objects.get(index) instanceof PrescriptionLabel){				((PrescriptionLabel) objects.get(index)).setFillColour(newFillColour);				((PrescriptionLabel) objects.get(index)).setTransparent(false);			}					}	}
	/**
	 * Changes the text colour of object which is selected
	 */
	public void changeTextColour(){
		Color newTextColour = JColorChooser.showDialog(Designer.getInstance(), "Text Color", Color.BLACK);
		if(newTextColour != null){
			PrescriptionObject obj = objects.get(getSelectedIndex());
			if(obj.isSelected() && obj instanceof PrescriptionBox){
				((PrescriptionBox) obj).setTextColour(newTextColour);
				setChanged();
			}else if(obj.isSelected() && obj instanceof PrescriptionLabel){				((PrescriptionLabel) obj).setTextColour(newTextColour);				setChanged();			}
		}
	}	/**	 * Sets the object's state to be selected on the prescription	 * @param index the index of the object to be marked as selected	 */
	public void setSelected(int index){				int i = 0;
		for(PrescriptionObject object : objects){		
			if(i == index){
				object.setSelected(true);
				Designer.getInstance().setSelectedIndex(i);
			}
			else{
				object.setSelected(false);
			}
			i++;
		}
	}
	/**
	 * Sets current box object to transparent or opaque
	 */
	public void transparent(){
		PrescriptionObject object = objects.get(getSelectedIndex());
		if(object.isSelected()){
			if(object.isTransparent()){
				object.setTransparent(false);
			}
			else{
				object.setTransparent(true);
			}
		}
		setChanged();
	}
	/**
	 * Clears the instance of the prescription
	 */
	public void clear(){
		instance = null;
		setUnchanged();
	}	/**	 * Gets the filename of the currently open prescription	 * @return the filename of the currently open prescription	 */
	public String getFilename(){
		return filename;
	}		/**	 * Finds the first instance of a box object on the prescription.	 * @return the first box added to the prescription, returns null if there are no box objects on the prescription	 */	public PrescriptionBox findFirstBox(){		if(objects.get(0) instanceof PrescriptionBox){			return (PrescriptionBox)objects.get(0);		}		for(int i = 0; i < objects.size(); ++i){			if(objects.get(i) instanceof PrescriptionBox){				return (PrescriptionBox)objects.get(i);			}		}		return null;	}
}